package com.dragons.dragonsvf.utils.secret;

import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class AesEncryptUtil {

    // 使用AES-128-CBC加密模式，key和iv需要为16字节（128位）
    // 建议实际使用时通过安全方式生成和存储密钥，不要硬编码在代码中
    private static final String KEY = "julongkeji062633"; // 16字节
    private static final String IV =  "JULONGSHANGMAO00";  // 16字节

    // 自定义安全字符集映射（替换标准Base64中的+/=）
    private static final Map<Character, Character> CUSTOM_BASE64_MAP = new HashMap<>();
    static {
        // 标准Base64字符集：ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
        // 将'+'替换为'-'，'/'替换为'*'，'='替换为'_'
        CUSTOM_BASE64_MAP.put('+', '-');
        CUSTOM_BASE64_MAP.put('/', '*');
        CUSTOM_BASE64_MAP.put('=', '_');
    }



    public static void main(String[] args) throws Exception {
//        String test = "dragons1314127";
        String test = "123456";
        /**
         * 加密结果: M0oAGC139cxTXeJ5kleFtQ__
         * 解密结果: dragons1314127
         * M0oAGC139cxTXeJ5kleFtQ__
         * M0oAGC139cxTXeJ5kleFtQ__
         */

        // 加密测试
        String encrypted = encrypt(test);
        System.out.println("加密结果: " + encrypted);
        // VIa54nSipPHD8HqiQjB-sQ__

        // 解密测试
        String decrypted = decrypt(encrypted);
        System.out.println("解密结果: " + decrypted);
    }



    /**
     * 加密方法（使用自定义安全Base64编码）
     * @param data 要加密的明文
     * @param key  16字节的加密密钥
     * @param iv   16字节的初始化向量
     * @return 加密后的自定义Base64字符串
     */
    public static String encrypt(String data, String key, String iv) throws Exception {
        try {
            // 校验密钥和IV长度
            validateKeyAndIV(key, iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 使用标准填充方式
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

            // 生成标准Base64并替换特殊字符
            String base64Str = Base64.encodeBase64String(encrypted);
            return replaceBase64SpecialChars(base64Str);
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    /**
     * 解密方法
     * @param data 自定义Base64格式的密文
     * @param key  16字节的解密密钥
     * @param iv   16字节的初始化向量
     * @return 解密后的明文
     */
    public static String decrypt(String data, String key, String iv) throws Exception {
        try {
            // 校验密钥和IV长度
            validateKeyAndIV(key, iv);

            // 还原标准Base64字符
            String standardBase64 = restoreBase64SpecialChars(data);
            byte[] encrypted = Base64.decodeBase64(standardBase64);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] original = cipher.doFinal(encrypted);
            return new String(original, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }

    /**
     * 使用默认密钥和IV加密
     */
    public static String encrypt(String data) throws Exception {
        return encrypt(data, KEY, IV);
    }

    /**
     * 使用默认密钥和IV解密
     */
    public static String decrypt(String data) throws Exception {
        if (StringUtils.isEmpty(data)) {
            return null;
        }
        return decrypt(data, KEY, IV);
    }

    /**
     * 替换Base64中的特殊字符（+/=）为安全字符
     */
    private static String replaceBase64SpecialChars(String base64Str) {
        StringBuilder sb = new StringBuilder();
        for (char c : base64Str.toCharArray()) {
            sb.append(CUSTOM_BASE64_MAP.getOrDefault(c, c));
        }
        return sb.toString();
    }

    /**
     * 恢复被替换的Base64特殊字符
     */
    private static String restoreBase64SpecialChars(String customStr) {
        // 反向映射
        Map<Character, Character> reverseMap = new HashMap<>();
        for (Map.Entry<Character, Character> entry : CUSTOM_BASE64_MAP.entrySet()) {
            reverseMap.put(entry.getValue(), entry.getKey());
        }

        StringBuilder sb = new StringBuilder();
        for (char c : customStr.toCharArray()) {
            sb.append(reverseMap.getOrDefault(c, c));
        }
        return sb.toString();
    }

    /**
     * 校验密钥和IV的合法性
     */
    private static void validateKeyAndIV(String key, String iv) {
        if (key == null || key.getBytes(StandardCharsets.UTF_8).length != 16) {
            throw new IllegalArgumentException("密钥必须为16字节");
        }
        if (iv == null || iv.getBytes(StandardCharsets.UTF_8).length != 16) {
            throw new IllegalArgumentException("IV必须为16字节");
        }
    }


}